﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;

namespace weixin.api.Jsapi
{
    /// <summary>
    /// 表单数据项
    /// </summary>
    public class FormItemModel
    {
        /// <summary>
        /// 表单键，request["key"]
        /// </summary>
        public string Key { set; get; }
        /// <summary>
        /// 表单值,上传文件时忽略，request["key"].value
        /// </summary>
        public string Value { set; get; }
        /// <summary>
        /// 是否是文件
        /// </summary>
        public bool IsFile
        {
            get
            {
                if (FileContent == null || FileContent.Length == 0)
                    return false;

                if (FileContent != null && FileContent.Length > 0 && string.IsNullOrWhiteSpace(FileName))
                    throw new Exception("上传文件时 FileName 属性值不能为空");
                return true;
            }
        }
        /// <summary>
        /// 上传的文件名
        /// </summary>
        public string FileName { set; get; }
        /// <summary>
        /// 上传的文件内容
        /// </summary>
        public byte[] FileContent { set; get; }
    }

    public class HttpUtil
    {

        //private const string sContentType = "application/x-www-form-urlencoded";
        //private const string sUserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
        public static string Send(string data, string url)
        {
            //return Send(Encoding.GetEncoding("UTF-8").GetBytes(data), url);
            return GetHtmlResponse(url);
        }

        public static string Send(byte[] data, string url)
        {
            Stream responseStream;
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            if (request == null)
            {
                throw new ApplicationException(string.Format("Invalid url string: {0}", url));
            }
            if (data != null && data.Length > 0)
            {
                request.Method = "POST";
                request.ContentLength = data.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(data, 0, data.Length);
                requestStream.Close();
            }
            else
            {
                request.Method = "GET";
            }
            try
            {
                responseStream = request.GetResponse().GetResponseStream();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            string str = string.Empty;
            using (StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("UTF-8")))
            {
                str = reader.ReadToEnd();
            }
            responseStream.Close();
            return str;
        }

        public static byte[] Send(string url)
        {
            Stream responseStream;
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            if (request == null)
            {
                throw new ApplicationException(string.Format("Invalid url string: {0}", url));
            }
            request.Method = "GET";
            try
            {
                responseStream = request.GetResponse().GetResponseStream();
                var memoryStream = new MemoryStream();
                const int bufferLength = 1024;
                byte[] temp = new byte[bufferLength];
                int actual = 0;
                while ((actual = responseStream.Read(temp, 0, bufferLength)) > 0)
                {
                    memoryStream.Write(temp, 0, actual);
                }
                responseStream.Close();
                byte[] buffer = memoryStream.ToArray();
                memoryStream.Close();
                return buffer;
            }
            catch (Exception exception)
            {
                return null;
            }
        }

        public static string GetHtmlResponse(string url, string method = "GET", string postdata = null, string postcode = "utf-8", string xAuth = "")
        {
            try
            {
                if (!url.ToLower().StartsWith("http://") && !url.ToLower().StartsWith("https://"))
                {
                    url = "http://" + url;
                }
                System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                req.Timeout = 10000;
                if (xAuth.Trim() != "")
                {
                    req.Headers.Add("X-Auth", xAuth);
                }
                req.Method = method.ToUpper();
                req.KeepAlive = false;
                if (req.Method == "POST" && !string.IsNullOrEmpty(postdata))
                {
                    byte[] buffer = System.Text.Encoding.GetEncoding(postcode).GetBytes(postdata);
                    req.ContentLength = buffer.Length;
                    using (System.IO.Stream reqStream = req.GetRequestStream())
                    {
                        reqStream.Write(buffer, 0, buffer.Length);
                        reqStream.Close();
                    }
                }

                System.Net.HttpWebResponse res = (System.Net.HttpWebResponse)req.GetResponse();
                System.IO.StreamReader sr = new System.IO.StreamReader(res.GetResponseStream());
                string result = sr.ReadToEnd();
                sr.Close();
                res.Close();
                return result;
            }
            catch
            {
                return "{\"errcode\":-1,\"errmsg\":\"调用接口错误\"}";
            }
        }

        /// <summary>/// 
        /// 使用Post方法获取字符串结果
        /// </summary>
        /// <param name="url"></param>/// 
        /// <param name="formItems">Post表单内容</param>
        /// <param name="cookieContainer"></param>
        /// <param name="timeOut">默认20秒</param>
        /// <param name="encoding">响应内容的编码类型（默认utf-8）</param>
        /// <returns></returns>
        public static string PostForm(string url, List<FormItemModel> formItems, CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            #region 初始化请求对象	
            request.Method = "POST";
            request.Timeout = timeOut;
            request.KeepAlive = true;
            request.Headers.Add("XX-Device-Type", "wxweb");
            #endregion
            string boundary = "----" + DateTime.Now.Ticks.ToString("x");
            //分隔符
            request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            //请求流
            var postStream = new MemoryStream();
            #region 处理Form表单请求内容	
            //是否用Form上传文件	
            var formUploadFile = formItems != null && formItems.Count > 0;
            if (formUploadFile)
            {
                //文件数据模板		
                string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + "\r\nContent-Type: application/octet-stream" + "\r\n\r\n";
                //文本数据模板		
                string dataFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"" + "\r\n\r\n{1}";
                foreach (var item in formItems)
                {
                    string formdata = null;
                    if (item.IsFile)
                    {
                        //上传文件				
                        formdata = string.Format(fileFormdataTemplate, item.Key, item.FileName);
                    }
                    else
                    {
                        //上传文本	
                        formdata = string.Format(dataFormdataTemplate, item.Key, item.Value);
                    }
                    //统一处理	
                    byte[] formdataBytes = null;
                    //第一行不需要换行		
                    if (postStream.Length == 0)
                        formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
                    else
                        formdataBytes = Encoding.UTF8.GetBytes(formdata);
                    postStream.Write(formdataBytes, 0, formdataBytes.Length);
                    //写入文件内容			
                    if (item.FileContent != null && item.FileContent.Length > 0)
                    {
                        postStream.Write(item.FileContent, 0, item.FileContent.Length);
                    }
                }       //结尾		
                var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
                postStream.Write(footer, 0, footer.Length);
            }
            else
            {
                request.ContentType = "application/x-www-form-urlencoded";
            }
            #endregion
            request.ContentLength = postStream.Length;
            #region 输入二进制流	
            if (postStream != null)
            {
                postStream.Position = 0;
                //直接写入流
                Stream requestStream = request.GetRequestStream();
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    requestStream.Write(buffer, 0, bytesRead);
                }
                postStream.Close();
            }
            #endregion
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            if (cookieContainer != null)
            {
                response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
            }
            using (Stream responseStream = response.GetResponseStream())
            {
                using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8))
                {
                    string retString = myStreamReader.ReadToEnd();
                    return retString;
                }
            }
        }
    }
}
